1. /* slflsdiv.cpp by K.Tsuru */
  2. // funstion ID = 213 DRADIX, BRADIX
  3. /**********************************************************************
  4. SLong class
  5. m/n
  6. It divides m by a small number n where 0 <= n < ULONG_MAX/m.Radix().
  7. To use IsDiv is better for SInteger.
  8. If rem != NULL the remainder is set on *rem.
  9. ***********************************************************************/
  10. #ifndef SN_H
  11. #include "sn.h"
  12. #endif
  13. static const char* const func = "LsDiv";
  14. SLong LsDiv(const SLong& m, ulong n, long* rem){
  15. if(rem != NULL) *rem = 0; //remainder = 0
  16. int m_sign = m.Sign(213);
  17. if(!n) m.SetError(m.DIVIDED_BY_ZERO, func, 213);
  18. if(n == 1uL || !m_sign) return m; // m = 0 or n = 1 --> *rem = 0
  19. if( n > m.SlOpMaxValue() ){
  20. m.SetError(m.OUT_OF_RANGE, func, 213);
  21. }
  22. int qh = (int)m.aHead, qt = (int)m.aTail;
  23. ulong rdx = m.Radix();
  24. SLong quot(m.Type(), 0); // SInteger is also Ok.
  25. if(qh <= 1){//The figures of m is two or under, including m < n.
  26. // s <= (R-1)*R+(R-1) = R^2 -1 < ULONG_MAX
  27. ulong s = (ulong)m[1]*(ulong)rdx + (ulong)m[0]; //It can be convert to ulong.
  28. quot.SetLong(long(s/n));
  29. if(rem != NULL) *rem = m_sign*long(s%n);
  30. if(quot.Sign()) quot.SetSign(m_sign);
  31. return quot;
  32. }
  33. //Here the figures of m is three or over. m >= R^2 > ULONG_MAX/R >= n, then quot != 0
  34. quot.valloc(m.Size(), -1);
  35. ulong t = 0;
  36. const fType* mv = m.ReadFigures();
  37. fType* qv = quot.figure.Elements();
  38. #ifndef NDEBUG
  39. quot.figure((uint)qh);
  40. #endif
  41. quot.figure.clear((uint)qh+1u);
  42. if(qt) quot.figure.clear(0, (uint)qt-1u);
  43. //It begins a calculation.
  44. int i; // The type must be "int".
  45. for(i = qh ; i >= qt; i--){
  46. t = t*rdx + (ulong)mv[i];
  47. qv[i] = fType(t/n);
  48. t = t - qv[i]*n; //faster than t %= n;
  49. }
  50. if(t){ //Here mv[i] = 0.
  51. for(; t && i >= 0; i--){
  52. t = t*rdx;
  53. qv[i] = fType(t/n);
  54. t = t - qv[i]*n;
  55. }
  56. qt = i < 0 ? 0 : i;
  57. }
  58. //It sets a remainder which has the same sign as m.
  59. if(rem != NULL) *rem = m_sign*(long)t;
  60. //Get figure positions.
  61. if(qh){
  62. while( !qv[qh] && (qh >= 0) ) qh--;
  63. while( !qv[qt] && (qt <= qh)) qt++;
  64. }
  65. #ifndef NDEBUG // quot != 0
  66. assert(qh >= 0 && qv[qh]);
  67. #endif
  68. quot.SetSign(m_sign);
  69. quot.aHead = (uint)qh;
  70. quot.aTail = (uint)qt;
  71. //It reduces the size if possible.
  72. if( 2u*(quot.aHead+1) <= quot.figure.size() ) quot.DoCutDown();
  73. return quot;
  74. }

slflsdiv.cpp : last modifiled at 2017/03/13 14:32:00(2,386 bytes)
created at 2017/10/07 10:26:49
The creation time of this html file is 2017/11/09 14:52:03 (Thu Nov 09 14:52:03 2017).